package org.dctmcommons;

import static org.dctmcommons.DctmCommonsConstants.PATH_SEPARATOR;

import java.util.UUID;

import com.documentum.fc.client.IDfFolder;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.common.DfDocbaseConstants;
import com.documentum.fc.common.DfException;

/**
 * <p>
 * Utility class for running integration tests against the repository,
 * providing methods to obtain/release sessions and setup/teardown test
 * folder hierarchies. Example usage:
 * </p>
 * <pre>
 * public class MyIntegrationTest() {
 *     @Test
 *     public void testQuery() throws DfException {
 *         final DctmCommonsTestContext ctx = DctmCommonsTestUtil.getContext();
 *         final String msg = MessageFormat.format("Connecting to {0} as {1}",
 *                                                 ctx.getRepository(),
 *                                                 ctx.getUsername());
 *         System.out.println(msg);
 *
 *         final IDfSession session = DctmCommonsTestUtil.getSession();
 *         assertThat(session, is(notNullValue));
 *     	   final String objectId = query(session, buildDql());
 *         DctmCommonsTestUtil.releaseSession(session);
 *         assertThat(objectId, is(notNullValue));
 *         // etc..
 *     }
 * }
 * </pre>
 * <p>
 * Please note that sessions are obtained lazily and cached thereafter in
 * ThreadLocal storage. Don't forget to release the session when it's no longer
 * required!
 * </p>
 * @author Mark Davidson
 */
public class DctmCommonsTestUtil {
	
	/** The path to the temp cabinet. */
    private static final String TEMP_CABINET_PATH = "/Temp";
	
	/** The instance of the DctmCommonsTestContext. */
	private static ThreadLocal<DctmCommonsTestContext> context =
		new ThreadLocal<DctmCommonsTestContext>() {
		@Override protected DctmCommonsTestContext initialValue() {
			return DctmCommonsTestContext.getInstance();
		}
	};

	/**
	 * Gets the test context.
	 * @return The test context
	 */
	public static DctmCommonsTestContext getContext() {
		return context.get();
	}
	
	/**
	 * Gets the session.
	 * @return The session
	 * @throws DfException The repository exception
	 */
	public static IDfSession getSession() throws DfException {
		return getContext().getSession();
	}
	
	/**
	 * Releases the session.
	 */
	public static void releaseSession() {
		getContext().releaseSession();
	}
	
    /**
     * Gets or creates a folder under the '/Temp' cabinet to hold objects
     * that are generated by unit tests.
     * @return The folder
     * @throws DfException The repository exception
     */
    public static IDfFolder createTestFolder() throws DfException {
		final IDfFolder folder = (IDfFolder) getSession().newObject(
											DfDocbaseConstants.DM_FOLDER);
		folder.setObjectName(UUID.randomUUID().toString());
		folder.link(TEMP_CABINET_PATH);
		folder.save();
		return folder;
    }
    
    /**
     * Creates the test folder.
     * @return The test folder path
     * @throws DfException The repository exception
     */
    public static String createTestFolderPath() throws DfException {
    	return TEMP_CABINET_PATH +
    		   PATH_SEPARATOR +
    		   createTestFolder().getObjectName();
    }

    /**
     * Teardown test objects.
     * @param basePath The base path
     * @param includeBaseFolder Whether to remove the base folder
     * @throws DfException The repository exception
     */
    public static void teardown(final String basePath,
    							final boolean includeBaseFolder)
    	throws DfException {
    	if (includeBaseFolder) {
	    	getContext().teardownFrom(basePath)
	    				.includeAllObjects()
	    				.build(getSession());
    	} else {
    		getContext().teardownFrom(basePath)
    					.includeAllChildObjects()
    					.build(getSession());
    	}
    }
}
